<?php

namespace addons\helper\controller\wxapp;

use think\Controller;
use think\Validate;
use think\Request;
use think\Session;
use think\Config;
use fast\Random;
use fast\Auth;
use addons\helper\library\Weapp;
use addons\helper\library\Alisms;
use app\admin\model\Admin;
use app\admin\model\helper\User;
use app\admin\model\helper\UserLog;

class Login extends Controller
{
    protected $config = [];

    public function _initialize()
    {
        $this->config = get_addon_config('helper');
        $this->config['SmsCodeExpireSec'] = (int) $this->config['SmsCodeExpireSec'] ?: 180;
        Request::instance()->filter('trim,strip_tags,htmlspecialchars,stripslashes');

                if (isset($_SERVER['HTTP_ORIGIN']) && $_SERVER['HTTP_ORIGIN']) {
                    $info = parse_url($_SERVER['HTTP_ORIGIN']);

                        header("Access-Control-Allow-Origin: " . $_SERVER['HTTP_ORIGIN']);


                    header('Access-Control-Allow-Credentials: true');
                    header('Access-Control-Max-Age: 86400');

                    if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {
                        if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD'])) {
                            header("Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS");
                        }
                        if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS'])) {
                            header("Access-Control-Allow-Headers: {$_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']}");
                        }
                        exit;
                    }
                }

    }
    /**
     * 登录页初始化数据
     *
     * @return void
     */
    public function init()
    {
        $token = $this->request->header('Token', '');
        $user = User::get(['token' => $token]);
        if ($token && $user) {
            if ($user['status'] === '0') {
                return json([
                    'code' => -1,
                    'msg' => '账号已被禁止登录小程序',
                    'data' => [
                        'config' => $this->getGlobalConfig()
                    ]
                ]);
            }
            $user->logintime = time();
            $user->token     = Random::uuid();
            $user->save();
        }
        
        return json([
            'code' => 0,
            'msg' => 'ok',
            'data' => [
                'config' => $this->getGlobalConfig(),   // 全局配置
                'token'  => $user['token'],             //新的token(如果有)
                'userId' => $user['user_id']
            ]
        ]);
    }
    /**
     * 微信登录
     *
     * @return void
     */
    public function wechatlogin()
    {
        if (!in_array('wechat', explode(',', $this->config['LoginType']))) {
            return json(['code' => 1, 'msg' => '已禁止微信一键登录']);
        }
        $code     = Request::instance()->post('code');
        $userInfo = Request::instance()->post('userInfo/a');

        if (!$code || !$userInfo) {
            return json(['code' => 1, 'msg' => '缺少必要参数']);
        }
        $session = Weapp::code2Session($this->config['AppID'], $this->config['AppSecret'], $code);

        if (isset($session['errcode']) && $session['errcode']) {
            return json(['code' => $session['code'], 'msg' => $session['errmsg']]);
        }
        $sessionKey = $session['session_key'];

        $decryptData = Weapp::decryptData($this->config['AppID'], $userInfo['encryptedData'], $userInfo['iv'], $sessionKey);
        if ($decryptData['code'] < 0) {
            return json(['code' => $decryptData['code'], 'msg' => $decryptData['msg']]);
        }

        $user = User::get(['wxopenid' => $decryptData['data']['openId']]);
        $ruleList = [];
        if ($user) {
            if ($user['status'] === '0') {
                return json(['code' => 1, 'msg' => '账号已被禁止登录小程序']);
            }
            $user->logintime = time();
            $user->token     = Random::uuid();
            $user->save();
            Session::set('admin',$user);
            $auth   = new Auth();
            $ruleList = array_values($auth->getRuleList($user->user_id));
            $admin = Admin::get(['id' => $user->user_id]);
            $this->recordLog('微信登录',$admin);
        }
        
        $data = [
            'openId'   => $decryptData['data']['openId'],
            'nickName' => $decryptData['data']['nickName'],
            'gender'   => $decryptData['data']['gender'],
            'city'     => $decryptData['data']['city'],
            'province' => $decryptData['data']['province'],
            'country'  => $decryptData['data']['country'],
            'avatar'   => $decryptData['data']['avatarUrl'],
            'unionId'  => isset($decryptData['data']['unionId']) ? $decryptData['data']['unionId'] : '',
            'config'   => $this->getGlobalConfig(),
            'token'    => $user ? $user->token : '',
            'userId'   => $user ? $user->user_id : '',
            'ruleList' => $ruleList
        ];
        return json(['code' => 0, 'data' => $data]);
    }
    /**
     * 手机号码登录
     *
     * @return void
     */
    public function mobileLogin()
    {
        if (!in_array('mobile', explode(',', $this->config['LoginType']))) {
            return json(['code' => 1, 'msg' => '已禁止手机号码登录']);
        }
        $mobile = Request::instance()->post('mobile');
        $captcha = Request::instance()->post('captcha/s');
        // 手机号码检查
        $check  = '/^(1(([345789][0-9])|(47)))\d{8}$/';
        if (!preg_match($check, $mobile)) {
            return json(['code' => 1, 'msg' => '手机号码格式不正确']);
        }
        // 验证码检查
        $code    = Session::get('captcha_sms.code');
        $time    = Session::get('captcha_sms.time');
        if ($time + $this->config['SmsCodeExpireSec'] < time()) {
            return json(['code' => 1, 'msg' => '验证码已过期，请重新发送。', 'data' => Session::get('captcha_sms')]);
        }
        if ($mobile !== Session::get('captcha_sms.mobile')) {
            return json(['code' => 1, 'msg' => '验证码不正确']);
        }
        if ($captcha !== $code) {
            return json(['code' => 1, 'msg' => '验证码不正确']);
        }
        // 账号检查
        $admin = Admin::get(['mobile' => $mobile]);
        if (!$admin) {
            return json(['code' => 1, 'msg' => '手机号码未登记']);
        }
        if ($admin['status'] == 'hidden') {
            return json(['code' => 1, 'msg' => '账号已被禁用']);
        }
        $user = User::get(['user_id' => $admin['id']]);
        if ($user) {
            if ($user['status'] === '0') {
                return json(['code' => 1, 'msg' => '账号已被禁止登录小程序']);
            }
            $user->logintime = time();
            $user->token     = Random::uuid();
            $user->save();
        } else {
            $data = [
                'user_id'     => $admin['id'],
                'token'       => Random::uuid(),
                'logintime'   => time()
            ];
            $user = User::create($data);
        }
        $auth = new Auth();
        $this->recordLog('手机号码登录',$admin);
        return json([
            'code' => 0,
            'msg'  => '登录成功',
            'data' => [
                'config'   => $this->getGlobalConfig(),
                'token'    => $user->token,
                'userId'   => $user->user_id,
                'ruleList' => array_values($auth->getRuleList($user->user_id))
            ]
        ]);
    }
    /**
     * 注册账号登录
     *
     * @return void
     */
    public function usernameLogin()
    {
        if (!in_array('username', explode(',', $this->config['LoginType']))) {
            return json(['code' => 1, 'msg' => '已禁止注册账号登录']);
        }
        $username = Request::instance()->post('account');
        $password = Request::instance()->post('password');
       /* $captcha  = Request::instance()->post('captcha');*/

        $rule = [

            'username|用户名' => 'require|length:3,30',
            'password|密码'  => 'require|length:3,30',
        ];
        $msg = [

            'username.require' => '请输入用户名',
            'username.length'  => '用户名长度必须在3~30之间',
            'password.require' => '请输入密码',
            'password.length'  => '密码长度必须在3~30之间',
        ];
        $data = [
            'username' => $username,
            'password' => $password,
       /*     'captcha'  => $captcha,*/
        ];
        $validate = new Validate($rule, $msg);
        $result   = $validate->check($data);
        if (!$result) {
            return json(['code' => 1, 'msg' => $validate->getError()]);
        }
        // 账号检查
        $admin = Admin::get(['username' => $username]);
        if (!$admin) {
            return json(['code' => 1, 'msg' => '账号或密码错误']);
        }
        if ($admin['status'] == 'hidden') {
            return json(['code' => 1, 'msg' => '账号已被禁用']);
        }
        if ($admin->password != md5(md5($password) . $admin->salt)) {
            return json(['code' => 1, 'msg' => '账号或密码错误']);
        }
        $user = User::get(['user_id' => $admin['id']]);
        if ($user) {
            if ($user['status'] === '0') {
                return json(['code' => 1, 'msg' => '账号已被禁止登录小程序']);
            }
            $user->logintime = time();
            $user->token     = Random::uuid();
            $user->save();
        } else {
            $data = [
                'user_id'     => $admin['id'],
                'token'       => Random::uuid(),
                'logintime'   => time()
            ];
            $user = User::create($data);
        }
        $auth = new Auth();
        $this->recordLog('账号登录',$admin);
        return json([
            'code' => 0,
            'msg'  => '登录成功',
            'data' => [
                'config'   => $this->getGlobalConfig(),
                'token'    => $user->token,
                'userId'   => $user->user_id,
                'ruleList' => array_values($auth->getRuleList($user->user_id))
            ]
        ]);
    }
    /**
     * 绑定账号（用户名密码方式）
     */
    public function bind()
    {
        $username = Request::instance()->post('username');
        $password = Request::instance()->post('password');
        $captcha  = Request::instance()->post('captcha');
        $userInfo = Request::instance()->post('userInfo/a');

        $rule = [
            'captcha|验证码'  => 'require|captcha',
            'username|用户名' => 'require|length:3,30',
            'password|密码'  => 'require|length:3,30',
        ];
        $msg = [
            'captcha.require'  => '请输入验证码',
            'username.require' => '请输入用户名',
            'username.length'  => '用户名长度必须在3~30之间',
            'password.require' => '请输入密码',
            'password.length'  => '密码长度必须在3~30之间',
        ];
        $data = [
            'username' => $username,
            'password' => $password,
            'captcha'  => $captcha,
        ];
        $validate = new Validate($rule, $msg);
        $result   = $validate->check($data);
        if (!$result) {
            return json(['code' => 1, 'msg' => $validate->getError()]);
        }
        // 账号检查
        $admin = Admin::get(['username' => $username]);
        if (!$admin) {
            return json(['code' => 1, 'msg' => '账号或密码错误']);
        }
        if ($admin['status'] == 'hidden') {
            return json(['code' => 1, 'msg' => '账号已被禁用']);
        }
        if ($admin->password != md5(md5($password) . $admin->salt)) {
            return json(['code' => 1, 'msg' => '账号或密码错误']);
        }
        if (User::get(['wxopenid' => $userInfo['openId']])) {
            return json(['code' => 1, 'msg' => '微信已绑定其它账号']);
        }
        $user = User::get(['user_id' => $admin['id']]);
        $data = [
            'user_id'     => $admin['id'],
            'token'       => Random::uuid(),
            'wxopenid'    => $userInfo['openId'],
            'wxnickname'  => $userInfo['nickName'],
            'wxgender'    => $userInfo['gender'],
            'wxcity'      => $userInfo['city'],
            'wxprovince'  => $userInfo['province'],
            'wxcountry'   => $userInfo['country'],
            'wxavatarurl' => $userInfo['avatar'],
            'wxunionid'   => $userInfo['unionId'],
        ];
        if ($user) {
            $user->save($data); // 用户已存在
        }else{
            $user = User::create($data); //新增用户
        }
        $auth = new Auth();
        $this->recordLog('绑定账号后登录',$admin);
        return json([
            'code' => 0,
            'msg'  => '绑定成功',
            'data' => [
                'config'   => $this->getGlobalConfig(),
                'token'    => $user->token,
                'userId'   => $user->user_id,
                'ruleList' => array_values($auth->getRuleList($user->user_id))
            ]
        ]);
    }
    /**
     * 绑定账号（手机方式）
     */
    public function bindMobile()
    {
        if (!(int) $this->config['IsMobileBind']) {
            $this->error('已禁止手机号码绑定');
        }
        $mobile = Request::instance()->post('mobile');
        $captcha = Request::instance()->post('captcha/s');
        $userInfo = Request::instance()->post('userInfo/a');

        // 手机号码检查
        $check  = '/^(1(([345789][0-9])|(47)))\d{8}$/';
        if (!preg_match($check, $mobile)) {
            return json(['code' => 1, 'msg' => '手机号码格式不正确']);
        }
        // 验证码检查
        $code    = Session::get('captcha_sms.code');
        $time    = Session::get('captcha_sms.time');
        if ($time + $this->config['SmsCodeExpireSec'] < time()) {
            return json(['code' => 1, 'msg' => '验证码已过期，请重新发送。']);
        }
        if ($mobile !== Session::get('captcha_sms.mobile')) {
            return json(['code' => 1, 'msg' => '验证码不正确']);
        }
        if ($captcha !== $code) {
            return json(['code' => 1, 'msg' => '验证码不正确']);
        }
        // 账号检查
        $admin = Admin::get(['mobile' => $mobile]);
        if (!$admin) {
            return json(['code' => 1, 'msg' => '手机号码未登记']);
        }
        if ($admin['status'] == 'hidden') {
            return json(['code' => 1, 'msg' => '账号已被禁用']);
        }
        if (User::get(['wxopenid' => $userInfo['openId']])) {
            return json(['code' => 1, 'msg' => '微信已绑定其它账号']);
        }
        $user = User::get(['user_id' => $admin['id']]);
        $data = [
            'user_id'     => $admin['id'],
            'token'       => Random::uuid(),
            'wxopenid'    => $userInfo['openId'],
            'wxnickname'  => $userInfo['nickName'],
            'wxgender'    => $userInfo['gender'],
            'wxcity'      => $userInfo['city'],
            'wxprovince'  => $userInfo['province'],
            'wxcountry'   => $userInfo['country'],
            'wxavatarurl' => $userInfo['avatar'],
            'wxunionid'   => $userInfo['unionId'],
        ];
        if ($user) {
            $user->save($data); // 用户已存在
        }else{
            $user = User::create($data); //新增用户
        }
        $auth = new Auth();
        $this->recordLog('绑定手机后登录',$admin);
        return json([
            'code' => 0,
            'msg'  => '绑定成功',
            'data' => [
                'config'   => $this->getGlobalConfig(),
                'token'    => $user->token,
                'userId'   => $user->user_id,
                'ruleList' => array_values($auth->getRuleList($user->user_id))
            ]
        ]);
    }
    /**
     * 生成图形验证码
     *
     * @return void
     */
    public function getCaptcha()
    {
        $config = array(
            'codeSet'  => '123456789',            // 验证码字符集合
            'useImgBg' => false,                  // 使用背景图片
            'fontSize' => 22,                     // 验证码字体大小(px)
            'useCurve' => false,                  // 是否画混淆曲线
            'useNoise' => true,                   // 是否添加杂点
            'length'   => 4,                      // 验证码位数
            'bg'       => array(255, 255, 255),   // 背景颜色
        );
        $captcha = new \think\captcha\Captcha($config);
        return $captcha->entry();
    }
    /**
     * 发送验证短信
     *
     * @return void
     */
    public function sendCaptchaSms()
    {
        // 手机号码检查
        $mobile = Request::instance()->post('mobile');
        $check  = '/^(1(([345789][0-9])|(47)))\d{8}$/';
        if (!preg_match($check, $mobile)) {
            return json(['code' => 1, 'msg' => '手机号码格式不正确']);
        }
        // 账号检查
        $admin  = Admin::get(['mobile' => $mobile]);
        if (!$admin) {
            return json(['code' => 1, 'msg' => '手机号码未登记']);
        }
        if ($admin['status'] === 'hidden') {
            return json(['code' => 1, 'msg' => '账号已被禁用']);
        }
        // 两次发送间隔检查 默认60秒
        if (Session::has('captcha_sms.time')) {
            if (time() < Session::get('captcha_sms.time') + 60) {
                $interval = Session::get('captcha_sms.time') + 60 - time();
                return json(['code' => 1, 'msg' => '请在' . $interval  . '秒后再发送']);
            }
        }
        // 生成6位数字验证码
        $code   = rand(0, 9) . rand(0, 9) . rand(0, 9) . rand(0, 9) . rand(0, 9) . rand(0, 9);

        // 记录session
        Session::set(
            'captcha_sms',
            [
                'mobile'      => $mobile,
                'code'        => strval($code),
                'time'        => time(),
            ]
        );
        // 模拟发送成功
        // return json(['code' => 0, 'msg' => '发送成功']);
        
        // 发送短信
        $accessKeyId     = $this->config['AliSmsAccessKeyId'];
        $accessKeySecret = $this->config['AliSmsAccessKeySecret'];
        $signName        = $this->config['AliSmsSignName'];
        $TemplateCode    = $this->config['AliSmsTemplateCode'];
        $TemplateParam   = '{"code":"' . $code . '"}';
        $ext             = [];
        $sms = Alisms::sendSms($accessKeyId, $accessKeySecret, $mobile, $signName, $TemplateCode, $TemplateParam);
        $sms = json_decode($sms, true);
        if ($sms['Code'] === 'OK') {
            return json(['code' => 0, 'msg' => '发送成功']);
        }
        return json(['code' => 1, 'msg' => '发送失败', 'data' => $sms]);
    }
    /**
     * 获取全局配置信息
     *
     * @return void
     */
    private function getGlobalConfig()
    {
        //上传配置
        $upload = Config::get('upload');
        $upload['cdnurl'] = $upload['cdnurl'] ? $upload['cdnurl'] : cdnurl('', true);
        $upload['uploadurl'] = $upload['uploadurl'] == 'ajax/upload' ? url('/addons/helper/wxapp.common/upload', [], '', true) : $upload['cdnurl'];
        
        $config = [
            'loginType'         => explode(',', $this->config['LoginType']),   //登录方式
            'loginIndexText'    => $this->config['LoginIndexText'],            //登录页文字信息
            'loginUsernameText' => $this->config['LoginUsernameText'],         //账号密码登录页文字信息
            'loginMobileText'   => $this->config['LoginMobileText'],           //手机号码登录页文字信息
            'isMobileBind'      => (int) $this->config['IsMobileBind'],        //是否可通过手机号绑定
            'upload'            => $upload
        ];
        return $config;
    }
    private function recordLog($title = '',$admin) {
        userLog::create([
            'title'     => $title,
            'content'   => '',
            'url'       => substr(request()->url(), 0, 1500),
            'user_id'   => $admin -> id,
            'username'  => $admin -> username,
            'useragent' => substr(request()->server('HTTP_USER_AGENT'), 0, 255),
            'ip'        => request()->ip()
        ]);
    }
}
